﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using System.Data;
using System.Data.Odbc;

using System.Xml;
using System.Xml.Serialization;
using System.ComponentModel;
using System.CodeDom.Compiler;
using System.Configuration;
using System.IO;


namespace WLMCoreLibrary
{

    /// <summary>
    /// Es la clase de donde se heredan las demas clases de todos los sistemas incluye los campos comunes en todos las clases y la automatizacion en el guardado y creacion de nuevos registros
    /// </summary>
    /// 
    [Serializable]
    [DesignerCategory("code")]    
    [GeneratedCode("xsd", "2.0.50727.3038")]
    public class BaseClass :  IConvertible
    {
        /// <summary>
        /// Conector a una base de datos interno de la base de datos referenciado desde fuera de la misma
        /// </summary>
        protected dbConnector ConexionDBInterna;
        //protected int _id;
        //protected DateTime _fechaCreacion;
        //protected DateTime _fechaModificacion;
        //protected int _idUsuario;
        //protected int _idUsuarioModificacion;
        protected string _AsociatedTable;

        [XmlAttribute()]
        public Guid GUID { get; set; }
        /// <summary>
        /// Identificador unico de el registro dentro de su tabla
        /// </summary>
        /// 
        [XmlAttribute()]
        public int id { get; set; }
        /// <summary>
        /// Fecha en la que el registro fue creado dentro de la base de datos [Serailizado como Atributo]
        /// </summary>
        /// 
        [XmlIgnore()]
        public DateTime fechaCreacion { get; set; }
        /// <summary>
        /// Fecha en la que fue actualizado por ultima ocacion el registro en la base de datos
        /// </summary>
        /// 
        [XmlIgnore()]
        public DateTime fechaModificacion { get; set; }
        /// <summary>
        /// Id Unico del usuario que creo el registro dentro de la base de datos
        /// </summary>
        /// 
        [XmlIgnore()]
        public int idUsuario { get; set; }
        /// <summary>
        /// Id Unico del usuario que realizo la ultima actualizacion del registro en la base de datos
        /// </summary>
        /// 
        [XmlIgnore()]
        public int idUsuarioModificacion { get;set; }

        /// <summary>
        /// Constructor de la clase base
        /// </summary>
        public BaseClass()
        {

        }

        //public BaseClass(ref dbConnector ConexionDB)
        //{
        //    ConexionDBInterna = ConexionDB;
        //}
        //public BaseClass(string contName, ref dbConnector ConexionDB)
        //{
        //    ConexionDBInterna = ConexionDB;
        //}
        public virtual void DesdeDataRow(DataRow registro)
        {
        }


        /// <summary>
        /// Guarda el registro en la base de datos
        /// </summary>
        public void Save()
        {
            try
            {
                idUsuarioModificacion = CurrentUser.IdUsuario;
            }
            catch
            {
                idUsuarioModificacion = 1;
            }

            fechaModificacion = DateTime.UtcNow.AddHours(-6);
            UpdateBind();
        }

        public void AssignConnection(ref dbConnector ConexionDB)
        {
            ConexionDBInterna = ConexionDB;
        }

        /// <summary>
        /// Creates a new record in the "AsociatedTable" table in database and get its key info
        /// </summary>
        public void getGUID()
        {
            WLMClassBinder classBinder = new WLMClassBinder(ref ConexionDBInterna);
            GUID = classBinder.NewGUID(_AsociatedTable);
            string queryString = "";
            queryString = "SELECT id,GUID,fechaCreacion,fechaModificacion,idUsuario,idUsuarioModificacion FROM "+_AsociatedTable+" WHERE GUID='" + GUID + "'";
            OdbcDataReader reader = ConexionDBInterna.ExecuteReader(queryString);
            if (reader.HasRows)
            {
                GetKeyData(reader);
            }
        }

        /// <summary>
        /// Creates a new record in the "AsociatedTable" table in database and get its key info
        /// </summary>
        /// <param name="databaseTable">The asociated database table name</param>
        public void getGUID(string databaseTable) {
            _AsociatedTable = databaseTable;
            getGUID();
            _AsociatedTable = "";
        }


        /// <summary>
        /// Funcion que se encarga de guardar la informacion en la tabla de la base de datos
        /// </summary>
        protected virtual void UpdateBind()
        { }

        public void Dispose()
        {
        }

        public string ToXML()
        {
            return WLMFunctions.ToXML(this);
        }

        public void GenerarArchivoXML(string nombreArchivo,string directorioSalida,BaseClass objeto)
        {
            StringBuilder salida = new StringBuilder();
            XmlSerializer serializer = new XmlSerializer(objeto.GetType());
            DirectoryInfo Direct = new DirectoryInfo(ConfigurationManager.AppSettings["sitePath"] + directorioSalida);
            if (!Direct.Exists)
                Direct.Create();



            string archivo = ConfigurationManager.AppSettings["sitePath"] + directorioSalida + nombreArchivo + ".xml";
            TextWriter tw = new StreamWriter(archivo);
            serializer.Serialize(tw, objeto);
            tw.Close();
            //WLMFunctions.ToXML(nombreArchivo, directorioSalida, objeto);
        }

        public void GenerarArchivoXML(BaseClass objeto)
        {
            GenerarArchivoXML(this.GetType().ToString()+"_"+id.ToString(),"/XML/",objeto);
        }

        public void GenerarArchivoXML(string nombreArchivo,BaseClass objeto)
        {
            GenerarArchivoXML(nombreArchivo, "/XML/", objeto);
        }

        protected void GetKeyData(OdbcDataReader reader)
        {
            if (!reader.IsDBNull(reader.GetOrdinal("GUID")))
            {
                //GuidConverter guidConverter=new GuidConverter();
                //if (guidConverter.IsValid(reader["GUID"].ToString()))
                //    GUID = (System.Guid)guidConverter.ConvertFromString(reader["GUID"].ToString());
                GUID = new Guid(reader["GUID"].ToString());
            }
            if (!reader.IsDBNull(reader.GetOrdinal("id")))
                id = (System.Int32)reader["id"];
            if (!reader.IsDBNull(reader.GetOrdinal("fechaCreacion")))
                fechaCreacion = Convert.ToDateTime(reader["fechaCreacion"]);
            if (!reader.IsDBNull(reader.GetOrdinal("fechaModificacion")))
                fechaModificacion = Convert.ToDateTime(reader["fechaModificacion"]);
            if (!reader.IsDBNull(reader.GetOrdinal("idUsuario")))
                idUsuario = (System.Int32)reader["idUsuario"];
            if (!reader.IsDBNull(reader.GetOrdinal("idUsuarioModificacion")))
                idUsuarioModificacion = (System.Int32)reader["idUsuarioModificacion"];
        }

        protected void GetKeyData(DataRow dataRow)
        {
            if (dataRow["GUID"]!=null)
            {
                GuidConverter guidConverter=new GuidConverter();
                if (guidConverter.IsValid(dataRow["GUID"].ToString()))
                    GUID = (System.Guid)guidConverter.ConvertFromString(dataRow["GUID"].ToString());
            }
            if (dataRow["id"] != null)
                id = (System.Int32)dataRow["id"];
            if (dataRow["fechaCreacion"] != null)
                fechaCreacion = (System.DateTime)dataRow["fechaCreacion"];
            if (dataRow["fechaModificacion"] != null)
                fechaModificacion = (System.DateTime)dataRow["fechaModificacion"];
            if (dataRow["idUsuario"] != null)
                idUsuario = (System.Int32)dataRow["idUsuario"];
            if (dataRow["idUsuarioModificacion"] != null)
                idUsuarioModificacion = (System.Int32)dataRow["idUsuarioModificacion"];
        }

        // interfaces
        #region Interfaces
        public TypeCode GetTypeCode()
        {
            return TypeCode.Object;
        }

        public bool ToBoolean(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public byte ToByte(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public char ToChar(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public sbyte ToSByte(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public short ToInt16(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public int ToInt32(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public long ToInt64(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public ushort ToUInt16(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public uint ToUInt32(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public ulong ToUInt64(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public float ToSingle(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public double ToDouble(IFormatProvider provider)
        {
            //return this.real;
            throw new InvalidCastException();
        }

        public decimal ToDecimal(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public DateTime ToDateTime(IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        public string ToString(IFormatProvider provider)
        {
            return "";
            //return this.real.ToString() + (this.imaginary >= 0 ? "+" : "") + this.imaginary.ToString() + "i";
        }

        public Object ToType(Type conversionType, IFormatProvider provider)
        {
            throw new InvalidCastException();
        }

        #endregion
    }

    [Serializable]
    public class BaseClassArray<T> : KeyedCollection<int, T> where T : BaseClass
    {

        public BaseClassArray()
        {
        }


        public BaseClassArray(IEnumerable<T> list)
        {
            foreach (T profile in list)
            {
                this.Add(profile);
            }
        }


        protected override int GetKeyForItem(T item)
        {
            return item.id;
        }

        public T UltimoElemento()
        {
            return Items[Items.Count - 1];
        }


    }

    //[Serializable]
    //public class BaseClassCollection
    //{
    //    protected dbConnector ConexionDBInterna;
    //    protected List<BaseClass> _items;
    //    public List<BaseClass> Items { get { return _items; } set { _items = value; } }
        

    //    public BaseClassCollection()
    //    {
    //        _items = new List<BaseClass>();
    //    }

    //    public string ToXML()
    //    {
    //        return WLMFunctions.ToXML(this);
    //    }

    //}


    interface baseClassFunctions
    {
        void UpdateBind();
    }
}
